package taskcycle

import (
	"GoMaestro/internal/dao"
	"GoMaestro/internal/entity"
	"GoMaestro/internal/entity/app"
	"GoMaestro/internal/logger"
	"GoMaestro/internal/strategy"
	"encoding/json"
	"log/slog"
)

// TaskCycle 发布引擎任务循环器
type TaskCycle struct {
	App app.App
	Dao *dao.MysqlDao
	strategy.ParamStrategy
	// 状态机
	states map[string]TaskState
}

func NewTaskCycle() *TaskCycle {
	t := &TaskCycle{
		states: make(map[string]TaskState),
	}
	// 初始化状态
	t.states[entity.StatusPackaged] = &PackagedState{}
	t.states[entity.StatusPackaging] = &PackagingState{}
	t.states[entity.StatusDeploying] = &DeployingState{}
	return t
}

// Check 开始检测任务状态并触发任务
func (t *TaskCycle) Check() {
	taskRecords, err := t.Dao.SelectTaskStatus()
	if err != nil {
		logger.DefaultLogger.Error(err.Error())
		return
	}

	for _, record := range taskRecords {
		if state, exists := t.states[record.Status]; exists {
			if err := state.Handle(t, &record); err != nil {
				logger.DefaultLogger.Error(err.Error())
			}
		}
	}
}

// triggerJenBuild 触发Jenkins构建
func (t *TaskCycle) triggerJenBuild(task entity.TaskRecord) (int, error) {
	err := t.GoStrategy1(task)
	if err != nil {
		return 0, err
	}
	t.App.ProjectAction = strategy.NewDefaultStrategy(task.CdJobName, t)
	if task.Status == entity.StatusPackaged && task.AutoDeploy {
		deployID, err := t.App.Deploy()
		if err != nil {
			return 0, err
		}
		slog.Info("正在执行构建JOB:", slog.Any("JOB", task.CdJobName), slog.Any("ID", deployID))
		return deployID, nil
	}
	return 0, nil
}

// GoStrategy1 使用流水线参数策略1
func (t *TaskCycle) GoStrategy1(task entity.TaskRecord) error {
	paramStrategy1 := new(strategy.ParamStrategy1)
	// 比较重要的一步，将app的参数绑定到cd阶段的策略中
	err := json.Unmarshal(task.PipelineParam, &paramStrategy1)
	if err != nil {
		return err
	}
	t.ParamStrategy = paramStrategy1
	return nil
}
